home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / libsrc / c / lib / strtold.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-04  |  2.4 KB  |  133 lines

  1. /*
  2. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. **
  4. ** This file is distributed under the terms listed in the document
  5. ** "copying.dj", available from DJ Delorie at the address above.
  6. ** A copy of "copying.dj" should accompany this file; if not, a copy
  7. ** should be available from where this file was obtained.  This file
  8. ** may not be distributed without a verbatim copy of "copying.dj".
  9. **
  10. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **
  13. ** changed strtod to _strtold (long double version)
  14. ** speed up and better accuracy for large exponents 
  15. ** D. Buerssner
  16. */
  17.  
  18. #include <stdlib.h>
  19. #include <ctype.h>
  20.  
  21. static long double powten[] =
  22. {
  23.     1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
  24.     1e512L, 1e1024L, 1e2048L, 1e4096L
  25. };
  26.  
  27. long double _strtold(const char *s, char **sret)
  28. {
  29.   long double r;    /* result */
  30.   int e, ne;    /* exponent */
  31.   int sign;    /* +- 1.0 */
  32.   int esign;
  33.   int flags=0;
  34.   int l2powm1;
  35.  
  36.   r = 0.0L;
  37.   sign = 1;
  38.   e = ne = 0;
  39.   esign = 1;
  40.  
  41.   while(*s && isspace(*s))
  42.     s++;
  43.  
  44.   if (*s == '+')
  45.     s++;
  46.   else if (*s == '-')
  47.   {
  48.     sign = -1;
  49.     s++;
  50.   }
  51.  
  52.   while ((*s >= '0') && (*s <= '9'))
  53.   {
  54.     flags |= 1;
  55.     r *= 10.0L;
  56.     r += *s - '0';
  57.     s++;
  58.   }
  59.  
  60.   if (*s == '.')
  61.   {
  62.     s++;
  63.     while ((*s >= '0') && (*s <= '9'))
  64.     {
  65.       flags |= 2;
  66.       r *= 10.0L;
  67.       r += *s - '0';
  68.       s++;
  69.       ne++;
  70.     }
  71.   }
  72.   if (flags == 0)
  73.   {
  74.     if (sret) *sret = s;
  75.     return 0.0L;
  76.   }
  77.  
  78.   if ((*s == 'e') || (*s == 'E'))
  79.   {
  80.     s++;
  81.     if (*s == '+')
  82.       s++;
  83.     else if (*s == '-')
  84.     {
  85.       s++;
  86.       esign = -1;
  87.     }
  88.     while ((*s >= '0') && (*s <= '9'))
  89.     {
  90.       e *= 10;
  91.       e += *s - '0';
  92.       s++;
  93.     }
  94.   }
  95.   if (esign < 0)
  96.   {
  97.       esign = -esign;
  98.       e = -e;
  99.   }
  100.   e = e - ne;
  101.   if (e < -4096)
  102.   {
  103.       /* possibly subnormal number, 10^e would overflow */
  104.       r *= 1.0e-2048L;
  105.       e += 2048;
  106.   }
  107.   if (e < 0)
  108.   {
  109.       e = -e;
  110.       esign = -esign;
  111.   }
  112.   if (e >= 8192)
  113.       e = 8191;
  114.   if (e)
  115.   {
  116.     long double d = 1.0L;
  117.     l2powm1 = 0;
  118.     while (e)
  119.     {
  120.      if (e & 1)
  121.        d *= powten[l2powm1];
  122.      e >>= 1;
  123.      l2powm1++;
  124.     }
  125.     if (esign > 0)
  126.     r *= d;
  127.     else
  128.     r /= d;
  129.   }
  130.   if(sret) *sret = s;
  131.   return r * sign;
  132. }
  133.